package com.example.qxfw.tourqx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.qxfw.common.entity.zy.SpecialFcst;
import com.example.qxfw.common.entity.zy.TourStations;
import com.example.qxfw.common.util.DateUtil;
import com.example.qxfw.tourqx.mapper.SpecialFcstMapper;
import com.example.qxfw.tourqx.service.JgybcxService;
import com.example.qxfw.ybzz.mapper.TourStationsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
public class JgybcxServiceImpl implements JgybcxService {
    @Autowired
    private TourStationsMapper tourStationsMapper;
    @Autowired
    private SpecialFcstMapper specialFcstMapper;
    // 日出日落时太阳的位置h＝-0.833°
    private double h = -0.833;
    // UTo为上次计算的日出日落时间,第一次计算时UTo＝180°
    private double UTo=180.0;
    //求从格林威治时间公元2000年1月1日到计算日天数days
    private static int dateDiff(Date time1, Date time2) {
        long ts1 = time1.getTime();
        long ts2 = time2.getTime();
        long ts = Math.abs(ts1 - ts2);
        return (int) (ts / (1000 * 60 * 60 * 24));
    }
    //求格林威治时间公元2000年1月1日到计算日的世纪数t
    public static double t_century(int days,  double UTo){
        return ((double)days+UTo/360)/36525;
    }
    //求太阳的平黄径
    public static double L_sun(double t_century){
        return (280.460+36000.770*t_century);
    }
    //求太阳的平近点角
    public static double G_sun(double t_century){
        return (357.528+35999.050*t_century);
    }
    //求黄道经度
    public static double ecliptic_longitude(double L_sun,double G_sun){
        return (L_sun+1.915*Math.sin(G_sun*Math.PI/180)+0.02*Math.sin(2*G_sun*Math.PI/180));
    }
    //求地球倾角
    public static double earth_tilt(double t_century){
        return (23.4393-0.0130*t_century);
    }
    //求太阳偏差
    public static double sun_deviation(double earth_tilt,double

            ecliptic_longitude){
        return (180/Math.PI*Math.asin(Math.sin(Math.PI/180*earth_tilt)*Math.sin(Math.PI/180*ecliptic_longitude)));
    }
    //求格林威治时间的太阳时间角GHA
    public static double GHA(double UTo,double G_sun,double ecliptic_longitude){
        return (UTo-180-1.915*Math.sin(G_sun*Math.PI/180)-0.02*Math.sin(2*G_sun*Math.PI/180)
                +2.466*Math.sin(2*ecliptic_longitude*Math.PI/180)
                -0.053*Math.sin(4*ecliptic_longitude*Math.PI/180));
    }
    //求修正值e
    public static double e(double h,double glat,double sun_deviation){
        return 180/Math.PI*Math.acos((Math.sin(h*Math.PI/180)-Math.sin
                (glat*Math.PI/180)*Math.sin(sun_deviation*Math.PI/180))/(Math.cos
                (glat*Math.PI/180)*Math.cos(sun_deviation*Math.PI/180)));
    }
    public static double UT_rise(double UTo,double GHA,double glong,double e){
        return (UTo-(GHA+glong+e));
    }
    //求日落时间
    public static double UT_set(double UTo,double GHA,double glong,double e){
        return (UTo-(GHA+glong-e));
    }
    //判断并返回结果（日出）
    public double result_rise(double UT,double UTo,double glong, double glat, int days){
        double d;
        if(UT>=UTo) d=UT-UTo;
        else d=UTo-UT;
        if(d>=0.1) {
            UTo=UT;
            UT=UT_rise(UTo, GHA(UTo,G_sun(t_century(days,UTo)),
                    ecliptic_longitude(L_sun(t_century(days,UTo)),
                            G_sun(t_century(days,UTo)))),
                    glong,
                    e(h,glat,sun_deviation(earth_tilt(t_century(days,UTo)),
                            ecliptic_longitude(L_sun(t_century(days,UTo)),
                                    G_sun(t_century(days,UTo))))));
            result_rise(UT,UTo,glong,glat,days);

        }
        return UT;
    }
    //判断并返回结果（日落）
    public double result_set(double UT,double UTo,double glong,double

            glat, int days){
        double d;
        if(UT>=UTo) d=UT-UTo;
        else d=UTo-UT;
        if(d>=0.1){
            UTo=UT;
            UT=UT_set(UTo,
                    GHA(UTo,G_sun(t_century(days,UTo)),
                            ecliptic_longitude(L_sun(t_century(days,UTo)),
                                    G_sun(t_century(days,UTo)))),
                    glong,
                    e(h,glat,sun_deviation(earth_tilt(t_century(days,UTo)),
                            ecliptic_longitude(L_sun(t_century(days,UTo)),
                                    G_sun(t_century(days,UTo))))));
            result_set(UT,UTo,glong,glat,days);
        }
        return UT;
    }
    //求时区
    public static int Zone(double glong){
        if(glong>=0) return ((int)(glong/15.0)+1);
        else return ((int)(glong/15.0)-1);
    }
    //日出时间
    private String getSunrise(double lon, double lat, String date) {
        double sunrise;
        String time = "2001-01-01";
        Date date1 = DateUtil.localDateTimeToDate(DateUtil.stringToLocalDateTime(time));
        Date date2 = DateUtil.localDateTimeToDate(DateUtil.stringToLocalDateTime(date));
        int days = dateDiff(date2,date1);
        sunrise = result_rise(UT_rise(UTo, GHA(UTo,G_sun(t_century(days,UTo)),
                ecliptic_longitude(L_sun(t_century(days,UTo)),
                        G_sun(t_century(days,UTo)))),
                lon,
                e(h,lat,sun_deviation(earth_tilt(t_century(days,UTo)),
                        ecliptic_longitude(L_sun(t_century(days,UTo)),
                                G_sun(t_century(days,UTo)))))),UTo,lon,lat,days);
        String result = date + " 日出时间: " + (int)(sunrise / 15 + Zone(lon)) + "时" + (int)(60 * (sunrise / 15 + Zone(lon) - (int)(sunrise / 15 + Zone(lon)))) + "分 ";
        return result;
    }
    //日落时间
    private String getSunset(double lon, double lat, String date) {
        double sunset;
        String time = "2001-01-01";
        Date date1 = DateUtil.localDateTimeToDate(DateUtil.stringToLocalDateTime(time));
        Date date2 = DateUtil.localDateTimeToDate(DateUtil.stringToLocalDateTime(date));
        int days = dateDiff(date2,date1);
        sunset=result_set(UT_set(UTo,
                GHA(UTo,G_sun(t_century(days,UTo)),
                        ecliptic_longitude(L_sun(t_century(days,UTo)),
                                G_sun(t_century(days,UTo)))),
                lon,
                e(h,lat,sun_deviation(earth_tilt(t_century(days,UTo)),
                        ecliptic_longitude(L_sun(t_century(days,UTo)),
                                G_sun(t_century(days,UTo)))))),UTo,lon,lat,days);
        String result = "日落时间：" + (int)(sunset / 15 + Zone(lon)) + "时" + (int)(60 * (sunset / 15 + Zone(lon) - (int)(sunset / 15 + Zone(lon)))) + "分";
        return result;
    }

    @Override
    public String[] txt(String date, String ntime, String landscape, String spot, String name) {
        String[] split = spot.split(",");
        String[] sunUpDowns = new String[split.length];
        for (int i = 0; i < split.length; i++) {
            TourStations tourStation = tourStationsMapper.selectOne(new LambdaQueryWrapper<TourStations>()
                    .eq(TourStations::getStationname, split[i]));
            String stationname = tourStation.getStationname();
            String up = getSunrise(tourStation.getLongitude(), tourStation.getLatitude(), date);
            String down = getSunset(tourStation.getLongitude(), tourStation.getLatitude(), date);
            String result = new StringBuilder().append(stationname).append(":")
                    .append(up).append(" - ").append(down)
                    .toString();
            sunUpDowns[i] = result;
            SpecialFcst specialFcst = new SpecialFcst();
            specialFcst.setTimechar(ntime);
            Date toDate = DateUtil.localDateTimeToDate(DateUtil.stringToLocalDateTime(date));
            specialFcst.setDatetime(toDate);
            specialFcst.setSuitable(result);
            specialFcst.setType(landscape);
            specialFcst.setTypename(split[i]);
            String substring = tourStation.getLocation().substring(0, 2);
            if (substring.equals("玉林")){
                List<SpecialFcst> typeNames = specialFcstMapper.selectList(new LambdaQueryWrapper<SpecialFcst>()
                        .eq(SpecialFcst::getTypename, split[i]));
                int[] numbers = new int[typeNames.size()];
                for (SpecialFcst typeName : typeNames) {
                    Integer stationId = Integer.valueOf(typeName.getStationid().substring(2));
                    numbers[i] = stationId;
                }
                int max = Arrays.stream(numbers).max().getAsInt();
                int num = max + 1;
                String formattedNumber = String.format("%04d", num);
                specialFcst.setStationid("YL"+formattedNumber);
            }
            specialFcstMapper.insert(specialFcst);
        }

        return sunUpDowns;
    }

    @Override
    public List<TourStations> getPredictionSpot() {
        return tourStationsMapper.selectList(new LambdaQueryWrapper<TourStations>()
        .select(TourStations::getStationname));
    }

    @Override
    public List<SpecialFcst> selectOfSpecialFcst(String startTime, String endTime) {
        Timestamp start = DateUtil.localDateTimeToTimestamp(DateUtil.stringToLocalDateTime(startTime));
        Timestamp end = DateUtil.localDateTimeToTimestamp(DateUtil.stringToLocalDateTime(endTime));
        return specialFcstMapper.selectList(new LambdaQueryWrapper<SpecialFcst>()
        .between(SpecialFcst::getDatetime, start, end));
    }

    @Override
    public List<SpecialFcst> selectByIdOfSpecialFcst(String id) {
        return specialFcstMapper.selectList(new LambdaQueryWrapper<SpecialFcst>()
        .eq(SpecialFcst::getId, id));
    }

    @Override
    public SpecialFcst save(SpecialFcst specialFcst) {
        int update = specialFcstMapper.update(specialFcst, new UpdateWrapper<SpecialFcst>()
                .eq("id", specialFcst.getId()));
        if (update > 0) {
            return specialFcst;
        }else {
            return null;
        }
    }


}
